<template>
  <div>
    <div class="rank-title"> 产品销量排行Top10 1</div>
    <div
      id="div1"
      ref="divRef"
      v-loading="loading"
      v-show="!loading"
      element-loading-background="rgba(122, 122, 122, 0.8)"
    >
      <p
        class="_item"
        v-for="(item, index) in randomArr"
        :key="index"
        :style="{
          fontSize: item.fontSize + 'px',
          color: item.color
        }"
      >
        {{ item.comboName }}
      </p>
    </div>
  </div>
</template>

<script setup>
import { topSalesApi } from '@/api/statistic'
const loading = ref(true)
const divRef = ref(null)
const randomArr = ref([])
const animationRunning = ref(true)
let radius = 120
let dtr = Math.PI / 180
let d = 300
let mcList = []
let lasta = 1
let lastb = 1
let distr = true
let tspeed = 20
let randomX = 0
let randomY = 0
let howElliptical = 1
let aA = null
let oDiv = null

onMounted(() => {
  init()
})

function init() {
  loading.value = true
  topSalesApi().then((res) => {
    randomArr.value = res?.data || []
    const fontSizes = [29, 20, 18, 17, 16, 15, 14, 13, 12, 11]
    const colors = [
      '#50FFED',
      '#49B2FF',
      '#50FFED',
      '#FF9F1B',
      '#FF9F1B',
      '#49B2FF',
      '#49B2FF',
      '#056AB5',
      '#056AB5',
      '#50FFED'
    ]
    randomArr.value = res?.data.map((item, index) => {
      return {
        ...item,
        fontSize: fontSizes[index],
        color: colors[index]
      }
    })

    nextTick(() => {
      oDiv = divRef.value
      aA = Array.from(oDiv.getElementsByTagName('p'))

      for (let i = 0; i < aA.length; i++) {
        const oTag = {
          offsetWidth: aA[i].offsetWidth,
          offsetHeight: aA[i].offsetHeight,
          cx: 0, // 添加 cx 属性
          cy: 0, // 添加 cy 属性
          cz: 0 // 添加 cz 属性
        }
        mcList.push(oTag)
      }

      sineCosine(0, 0, 0)
      positionAll()
      setInterval(() => {
        update()
      }, 300)
      setInterval(() => {
        // 生成随机的滚动方向
        randomX = Math.random() > 0.5 ? 1 : -1
        randomY = Math.random() > 0.5 ? 1 : -1
      }, 500)
      loading.value = false
    })
  })
}
onActivated(() => {
  loading.value = true
  topSalesApi().then((res) => {
    randomArr.value = res?.data || []
    const fontSizes = [25, 20, 18, 17, 16, 15, 14, 13, 12, 11]
    const colors = [
      '#50FFED',
      '#49B2FF',
      '#50FFED',
      '#FF9F1B',
      '#FF9F1B',
      '#49B2FF',
      '#49B2FF',
      '#056AB5',
      '#056AB5',
      '#50FFED'
    ]
    randomArr.value = res?.data.map((item, index) => {
      return {
        ...item,
        fontSize: fontSizes[index],
        color: colors[index]
      }
    })
    loading.value = false
  })
})
function update() {
  if (!animationRunning.value) return // 只有当 animationRunning 为真时才更新

  let a = randomX * tspeed
  let b = randomY * tspeed

  lasta = a
  lastb = b

  if (Math.abs(a) <= 0.01 && Math.abs(b) <= 0.01) {
    return
  }

  let c = 0
  sineCosine(a, b, c)
  doRotation()
  doPosition()
  depthSort()
}

function depthSort() {
  aA.sort((vItem1, vItem2) => {
    if (vItem1.cz > vItem2.cz) {
      return -1
    } else if (vItem1.cz < vItem2.cz) {
      return 1
    } else {
      return 0
    }
  })

  aA.forEach((item, i) => {
    item.style.zIndex = i
  })
}

function positionAll() {
  const max = mcList.length
  const aTmp = []
  const oFragment = document.createDocumentFragment()

  // 随机排序
  aA.forEach((item) => aTmp.push(item))
  aTmp.sort(() => Math.random() - 0.5)

  aTmp.forEach((item) => oFragment.appendChild(item))

  oDiv.appendChild(oFragment)

  for (let i = 1; i < max + 1; i++) {
    let phi, theta
    if (distr) {
      phi = Math.acos(-1 + (2 * i - 1) / max)
      theta = Math.sqrt(max * Math.PI) * phi
    } else {
      phi = Math.random() * Math.PI
      theta = Math.random() * (2 * Math.PI)
    }

    mcList[i - 1].cx = radius * Math.cos(theta) * Math.sin(phi)
    mcList[i - 1].cy = radius * Math.sin(theta) * Math.sin(phi)
    mcList[i - 1].cz = radius * Math.cos(phi)

    const left = `${mcList[i - 1].cx + oDiv.offsetWidth / 2 - mcList[i - 1].offsetWidth / 2}px`
    const top = `${mcList[i - 1].cy + oDiv.offsetHeight / 2 - mcList[i - 1].offsetHeight / 2}px`
    aA[i - 1].style.top = top
    aA[i - 1].style.left = left
  }
}

function doPosition() {
  const l = oDiv.offsetWidth / 2
  const t = oDiv.offsetHeight / 2
  mcList.forEach((item, i) => {
    const left = `${item.x + l - item.offsetWidth / 2}px` // 使用 item.x 替换 item.cx
    const top = `${item.y + t - item.offsetHeight / 2}px` // 使用 item.y 替换 item.cy
    const offsetWidth = item.offsetWidth
    const offsetHeight = item.offsetHeight
    if (offsetHeight + top > 159) {
      // aA[i].style.top = top - (top + offsetHeight - 159)
    }
    aA[i].style.top = top

    if (offsetWidth + left > 394) {
      aA[i].style.left = left - (left + offsetWidth - 394)
    } else {
      aA[i].style.left = left
    }
    // aA[i].style.fontSize = `${Math.ceil((12 * item.scale) / 2) + 8}px`

    aA[i].style.filter = `alpha(opacity=${100 * item.alpha})`
    aA[i].style.opacity = item.alpha
  })
}

function doRotation() {
  // 计算当前的旋转角度

  const { sa, ca, sb, cb, sc, cc } = sineCosine(lasta, lastb, 0) // 使用 lasta 和 lastb 作为当前的角度

  mcList.forEach((item, i) => {
    let rx1 = item.cx
    let ry1 = item.cy * ca + item.cz * -sa
    let rz1 = item.cy * sa + item.cz * ca

    let rx2 = rx1 * cb + rz1 * sb
    let ry2 = ry1
    let rz2 = rx1 * -sb + rz1 * cb

    let rx3 = rx2 * cc + ry2 * -sc
    let ry3 = rx2 * sc + ry2 * cc
    let rz3 = rz2

    item.cx = rx3
    item.cy = ry3
    item.cz = rz3

    const per = d / (d + rz3)

    item.x = howElliptical * rx3 * per - howElliptical * 2
    item.y = ry3 * per
    item.scale = per
    item.alpha = per

    item.alpha = (item.alpha - 0.6) * (10 / 6)
  })
}

function sineCosine(a, b, c) {
  const sa = Math.sin(a * dtr)
  const ca = Math.cos(a * dtr)
  const sb = Math.sin(b * dtr)
  const cb = Math.cos(b * dtr)
  const sc = Math.sin(c * dtr)
  const cc = Math.cos(c * dtr)

  return { sa, ca, sb, cb, sc, cc }
}

// function startAnimation() {
//   animationRunning.value = true
//   update()
// }

// function stopAnimation() {
//   animationRunning.value = false
// }
</script>

<style scoped>
#div1 {
  position: relative;
  background: no-repeat center / contain
    url('https://img0.baidu.com/it/u=3113157945,7869417&fm=253&fmt=auto&app=120&f=JPEG');
  width: 400px;
  height: 164px;
  background: rgba(92, 137, 237, 0.16);
  border-radius: 0px 0px 0px 0px;
  border: 3px solid rgba(126, 166, 255, 0.38);
  overflow: hidden;
  /* margin: 20px auto 0; */
}
.rank-title {
  padding-left: 51px;
  width: 332px;
  height: 38px;
  color: #fff;
  font-family: 'HarmonyOS Sans SC';
  font-size: 20px;
  font-weight: bold;
  line-height: 38px; /* 92.308% */
  background-image: url('../../assets/images/title-l-bg.png');
  background-size: 100% 100%;
  background-repeat: no-repeat;
  margin-bottom: 30px;
  margin-top: 20px;
}
#div1 ._item {
  position: absolute;
  top: 0px;
  left: 0px;
  font-family: Microsoft YaHei;
  font-weight: bold;
  text-decoration: none;
  padding: 3px 6px;
}

._item {
  white-space: nowrap;
  /* width: 100%;
  height: 50px;
  border-radius: 10px; */
}
</style>
